Übung: Deinen ersten Workflow per TowelScript deployen
Was du in dieser Übung lernst: Du baust einen dreistufigen Workflow vollständig aus Claude Code heraus — schreiben, prüfen, deployen, ausführen, Ergebnis kontrollieren. Dabei durchläufst du zum ersten Mal die komplette Werkzeugkette und siehst, wie sich die Fallstricke aus Einheit 4 in der Praxis bemerkbar machen.
Die API für diese Übung
Wir nutzen dieselbe öffentliche API wie in Kurs 5:
| Base URL | https://69cde52533a09f831b7c9fa5.mockapi.io/api/v1 |
| Ressource | contacts |
| Endpunkte | GET /contacts, POST /contacts, GET /contacts/:id, PUT /contacts/:id, DELETE /contacts/:id |
Ein Kontakt hat die Felder name, company und email.
Die API ist für alle Teilnehmer gemeinsam sichtbar. Lösche deine Testkontakte am Ende wieder — genauso, wie du es mit einem echten Zielsystem tun würdest.
Das Szenario
Eine Anfrage kommt als formloser E-Mail-Text herein. Irgendwo darin steht, wer geschrieben hat, für welche Firma und unter welcher Adresse. Dein Workflow soll daraus einen sauberen Kontakt machen und ihn im Zielsystem anlegen.
[ form ] → [ ai ] → [ http.post ]
Freitext Absender Kontakt in der
entgegen- extrahieren API anlegen
nehmen
Teil 1: Vorbereiten
Aufgabe 1 — Umgebung prüfen
Lass dir deine Projekte auflisten und merke dir die ID des Projekts, in dem du arbeiten willst.
„Liste meine 42°flow-Projekte auf."
Was passieren sollte
Das Werkzeug project_list liefert eine Liste mit id, name und workflow_count. Wenn hier deine echten Projekte stehen, ist die Verbindung in Ordnung. Kommt eine leere Liste oder ein 401, geh zurück zu Einheit 2.
Aufgabe 2 — Node-Typen nachschlagen
Bevor du schreibst: Welche Node-Typen brauchst du für Formular, KI-Auswertung und REST-Request? Und welche Optionen kennt der Formular-Node?
Mögliche Lösung anzeigen
Aus towelscript_catalog:
| Aufgabe | Node-Typ | Agent |
|---|---|---|
| Formular | form | Agents::WebFormAgent |
| KI-Auswertung | ai | Agents::GenAiAgent |
| REST-Request | http.post | Agents::PostAgent |
Aus agent_docs mit towelscript_type: "form": secret, form_fields, response_text, custom_css, hmac_secret, ip_allowlist.
Wichtig ist form_fields — ein JSON-Array als String, mit name, label, type je Feld.
Teil 2: Den Quelltext schreiben
Aufgabe 3 — TowelScript formulieren
Schreibe den Workflow. Anforderungen:
- Das Formular hat ein mehrzeiliges Pflichtfeld
freitext - Der KI-Node gibt JSON zurück, mit den Feldern
name,company,email - Der Post-Node sendet einen JSON-Body mit genau diesen drei Feldern — und nichts sonst
Denk an drei Dinge aus Einheit 4: einfache Anführungszeichen für das JSON in form_fields, dreifache für den Prompt, und payload: mit Doppelpunkt.
Mögliche Lösung anzeigen
module academy
flow kontaktanfrage {
node eingang: form {
secret: "academy-kurs6"
form_fields: '[{"name":"freitext","label":"E-Mail-Text einfuegen","type":"textarea","rows":8,"required":true}]'
response_text: "Danke - die Anfrage wird verarbeitet."
}
node extrahieren: ai {
model: "gus:tav"
output_format: "json"
prompt_template: """Extrahiere den Absender aus dem folgenden E-Mail-Text.
Gib ausschliesslich ein JSON-Objekt zurueck, ohne Einleitung und ohne Markdown.
Zielschema:
{"name": "Vor- und Nachname", "company": "Firmenname", "email": "E-Mail-Adresse oder null"}
E-Mail-Text:
{{ freitext }}"""
}
node anlegen: http.post {
post_url: "https://69cde52533a09f831b7c9fa5.mockapi.io/api/v1/contacts"
method: "post"
content_type: "json"
no_merge: true
payload: {
name: "{{ name }}",
company: "{{ company }}",
email: "{{ email }}"
}
}
eingang -> extrahieren -> anlegen
}
Zu den drei Optionen des Post-Nodes, die leicht übersehen werden:
content_type: "json"— sonst wird der Body als Formularfelder gesendetno_merge: true— sonst hängt der Agent die komplette eingehende Payload mit an, inklusivelast_messageundworkflow_run_idpayload:stattpayload— sonst sind die Verbindungen weg
Teil 3: Prüfen, bevor etwas passiert
Aufgabe 4 — Die Prüfkette durchlaufen
Lass den Quelltext prüfen — mit allen drei Werkzeugen, nicht nur mit check.
„Prüfe diesen TowelScript-Quelltext mit check, compile und graph."
Worauf du achten musst
towelscript_check liefert:
{ "valid": true, "errors": [], "warnings": [],
"stats": { "lines": 37, "nodes": 3, "flows": 1, "modules": 1 } }
nodes: 3 — stimmt.
towelscript_graph liefert:
{ "flows": [ { "name": "kontaktanfrage",
"edges": [
{ "from": "eingang", "to": "extrahieren", "kind": "data" },
{ "from": "extrahieren", "to": "anlegen", "kind": "data" }
] } ] }
Zwei Kanten. Wäre edges leer, hättest du irgendwo einen Block ohne Doppelpunkt.
towelscript_compile zeigt die Optionen, die wirklich am Agent landen. Prüfe hier besonders den Post-Node — steht payload dort als verschachteltes Objekt?
"payload": {
"company": "{{ company }}",
"email": "{{ email }}",
"name": "{{ name }}"
}
Wenn name, company und email stattdessen direkt neben post_url stehen, hast du die Blockschreibweise erwischt.
Aufgabe 5 — Den falschen Weg einmal bewusst gehen
Ändere payload: { in payload { und lass erneut prüfen. Notiere, was jedes der drei Werkzeuge meldet.
Mögliche Lösung anzeigen
| Werkzeug | Meldung |
|---|---|
towelscript_check | valid: true, keine Fehler, keine Warnungen |
towelscript_graph | edges: [] |
towelscript_compile | links: [], und name/company/email liegen flach neben post_url |
Das ist die Lehre dieser Übung: check allein ist wertlos für diese Fehlerklasse. Wärst du nur nach valid: true gegangen, hättest du drei unverbundene Agents deployt und den Fehler erst Stunden später im Log gesucht.
Teil 4: Deployen und ausführen
Aufgabe 6 — Deployen
„Deploye das als neuen Workflow mit dem Namen Übung 6 — Kontaktanfrage in Projekt <deine ID>."
Was zurückkommt
{
"success": true,
"workflow_id": 134,
"workflow_name": "Übung 6 — Kontaktanfrage",
"agent_count": 3,
"message": "Workflow deployed with 3 agents"
}
Merk dir die workflow_id — du brauchst sie für alles Weitere.
Öffne den Workflow jetzt einmal im Designer. Die Agents liegen wahrscheinlich übereinander: TowelScript ordnet nichts an. Dass die Verbindungen stimmen, siehst du trotzdem.
Aufgabe 7 — Struktur gegenprüfen
Lass dir den deployten Workflow zeigen und vergleiche mit deiner Absicht.
Worauf du achten musst
workflow_show liefert pro Agent sources und receivers. Die Kette muss durchgehen:
| Agent | sources | receivers |
|---|---|---|
eingang | – | extrahieren |
extrahieren | eingang | anlegen |
anlegen | extrahieren | – |
Außerdem fällt auf: Das Formular-Secret steht als "[REDACTED]" da. Der Server gibt Geheimnisse nicht heraus — auch nicht an dich. Dazu mehr in Einheit 11.
Aufgabe 8 — Echt ausführen
Starte den Workflow mit einem realistischen E-Mail-Text.
„Führe Workflow <ID> aus, mit diesem Freitext: …"
Nimm zum Beispiel:
Hallo zusammen,
wir hatten uns auf der Messe in Hannover kurz unterhalten. Ich wuerde gern ein
Angebot fuer die Automatisierung unserer Rechnungseingangspruefung bekommen.
Viele Gruesse
Dr. Anke Reinhardt
Leiterin Digitalisierung
Nordwerk Praezisionstechnik GmbH
a.reinhardt@nordwerk-pt.example
Was passieren sollte
workflow_run liefert sofort:
{
"run_id": "0b1abc97-c4ae-4483-b736-695d3375805f",
"status": "queued",
"entry_agent": { "id": 1900, "name": "eingang" },
"entry_message_id": 29213
}
queued, nicht completed — der Workflow läuft asynchron weiter. Die run_id ist dein Faden durch alles, was jetzt folgt.
Aufgabe 9 — Ergebnis prüfen
Kontrolliere auf zwei Wegen: im Workflow und im Zielsystem.
Mögliche Lösung anzeigen
Im Workflow — agent_messages auf den KI-Agent zeigt, was die Extraktion geliefert hat:
{
"name": "Dr. Anke Reinhardt",
"company": "Nordwerk Präzisionstechnik GmbH",
"email": "a.reinhardt@nordwerk-pt.example",
"last_message": { "freitext": "Hallo zusammen, …" },
"workflow_run_id": "0b1abc97-…"
}
Beachte: Die drei Felder liegen oben, nicht unter generation — das bewirkt output_format: "json". Und die ursprüngliche Payload ist unter last_message erhalten.
Die KI hat außerdem „Praezisionstechnik" zu „Präzisionstechnik" korrigiert. Ob das erwünscht ist, ist eine fachliche Entscheidung — festhalten solltest du es auf jeden Fall.
Im Log — agent_logs auf den Post-Agent zeigt den tatsächlich gesendeten Request:
Preparing POST request to https://69cde52533a09f831b7c9fa5.mockapi.io/api/v1/contacts
headers: {"Content-Type" => "application/json; charset=utf-8"}
Full request: {method: "POST", …, body: "{\"company\":\"Nordwerk Präzisionstechnik GmbH\",
\"email\":\"a.reinhardt@nordwerk-pt.example\",\"name\":\"Dr. Anke Reinhardt\"}"}
Received response status 201
201 — angelegt. Und der Body enthält genau drei Felder, weil no_merge: true gesetzt ist.
Im Zielsystem — ein GET auf die API zeigt den neuen Kontakt.
Teil 5: Aufräumen
Aufgabe 10 — Testdaten entfernen
Lösche deinen Testkontakt aus der API. Den Workflow kannst du behalten — du brauchst ihn in Einheit 10 und in der zweiten Übung wieder.
Wenn du einen Workflow doch löschen willst: workflow_export liefert das vollständige JSON. Sichere es. workflow_delete hat keinen Papierkorb.
Was du jetzt kannst
- Node-Typen und Optionen nachschlagen, statt zu raten
- Einen vollständigen Workflow in TowelScript schreiben
- Die Prüfkette
check→compile→graphdurchlaufen und den Unterschied benennen - Deployen, ausführen und das Ergebnis auf drei Ebenen kontrollieren: Nachricht, Log, Zielsystem